package com.spring.component.link;

/**
 * 双向链表
 * 
 * @param <T>
 */
public class DupleNode<T> extends Node {

  private DupleNode prev;
  /** 环切点的对应环的上一个节点 */
  private DupleNode rp;

  public DupleNode(DupleNode prev, DupleNode next, T value) {
    this.prev = prev;
    this.next = next;
    this.value = value;
  }

  public DupleNode getPrev() {
    return prev;
  }

  public DupleNode setPrev(DupleNode prev) {
    DupleNode n = this.prev;
    this.prev = prev;
    return n;
  }

  @Override
  public DupleNode getNext() {
    return (DupleNode) super.getNext();
  }

  @Override
  public DupleNode getNext(int i) {
    return (DupleNode) super.getNext(i);
  }

  @Override
  public DupleNode setNext(Node node) {
    return (DupleNode) super.setNext(node);
  }

  /**
   * 获取当前节点前面第i个节点
   * 
   * @param i
   * @return
   */
  public DupleNode getPrev(int i) {
    if (i < 0) {
      return null;
    } else if (i == 0) {
      return this;
    } else {
      DupleNode tmpNode = this.getPrev();
      for (int j = 1; j < i; j++) {
        if (tmpNode == null) {
          return null;
        }
        tmpNode = tmpNode.getPrev();
      }
      return tmpNode;
    }
  }

  @Override
  public DupleNode getLastNode() {
    return (DupleNode) super.getLastNode();
  }

  /**
   * 判断链表是否是完全闭环
   * 
   * @return
   */
  public boolean isPrefectRing() {
    DupleNode node = this;
    while (node.prev != null) {
      node = node.prev;
      if (node == this) {
        return true;
      }
    }
    return false;
  }

  /**
   * 获得头结点,如果链表完全闭环，返回null
   * 
   * @return
   */
  public DupleNode getHeadNode() {
    if (isPrefectRing()) {
      return null;
    }
    DupleNode node = this;
    while (node.prev != null) {
      node = node.prev;
    }
    return node;
  }

  /**
   * 反向链表，如果链表存在闭环，将抛出异常
   * 
   * @return
   * @throws Exception
   */
  public DupleNode reverse() throws Exception {
    if (this.isHavRing()) {
      throw new Exception("链表中存在闭环，不支持反向");
    }
    DupleNode dupleNode = this.getHeadNode();
    DupleNode temp = null;
    do {
      if (temp != null) {
        dupleNode = temp;
      }
      temp = dupleNode.prev;
      dupleNode.prev = dupleNode.getNext();
      dupleNode.next = temp;
      temp = dupleNode.prev;
    } while (temp != null);
    return dupleNode;
  }

  /**
   * 判断当前节点是否是环切点
   * 
   * @return
   */
  public boolean isRingCutPoint() {
    return this.prev.next == this;
  }

}
